#include "gamehome.h"
#include<QPointF>
#include<QPushButton>
#include"gameselect.h"
#include<qrandom.h>
gamehome::gamehome(QWidget *parent) : QWidget(parent)
{
    //   h: 1200   w:  1200
    this->setWindowTitle("贪吃蛇");

    QPushButton* sbn=new QPushButton(this);
    QPushButton* ebn=new QPushButton(this);
    QFont font("微软雅黑",26);
    sbn->setFont(font);
    ebn->setFont(font);
    sbn->setText("开始游戏");
    ebn->setText("暂停游戏");
    sbn->setGeometry(1220,160,250,150);
    ebn->setGeometry(1220,800,250,150);
    //初始化贪吃蛇
    createNewFood();
    snakeList.push_front(QRectF(200,400,50,50));
    //    snakeList.push_back(QRectF(200,250,50,50));
    //    snakeList.push_back(QRectF(200,300,50,50));
    moveUp();
    moveUp();
    timer=new QTimer(this);
    connect(timer,&QTimer::timeout,this,[=](){
        int cnt=1;

        if(snakeList.front().intersects(FoodRect))
        {
            createNewFood();    //如果吃到食物再构造一个食物
            cnt++;      //为什么吃到食物后cnt要++呢？因为这样才能确保进入下面循环两次(能够给蛇多增加一个结点，因为执行了2次push_front和1次pop_back)
        }
        while(cnt--)    //为什么这里不能一直处在循环中呢?因为这样就不能够执行下面更新链表(蛇结点)的代码了
        {
            switch(moveDirect)
            {
            case SnakeDirect::UP:
                moveUp();
                break;
            case SnakeDirect::DOWN:
                moveDown();
                break;
            case SnakeDirect::LEFT:
                moveLeft();
                break;
            case SnakeDirect::RIGHT:
                moveRight();
                break;
            }
        }
        snakeList.pop_back();  //每次移动完删除最后一个结点
        update();   //更新链表
    });
    connect(sbn,&QPushButton::clicked,this,[=](){
        timer->start(kDefaultTimeout);

    });
    connect(ebn,&QPushButton::clicked,this,[=](){
        gameselect* gs=new gameselect;
        isGameStart=false;
        timer->stop();
    });
    QPushButton* left_move=new QPushButton(this);
    QPushButton* right_move=new QPushButton(this);
    QPushButton* up_move=new QPushButton(this);
    QPushButton* down_move=new QPushButton(this);
    up_move->setText("↑");
    down_move->setText("↓");
    left_move->setText("←");
    right_move->setText("→");
    left_move->setGeometry(1220,440,70,70);
    right_move->setGeometry(1380,440,70,70);
    up_move->setGeometry(1300,350,70,70);
    down_move->setGeometry(1300,530,70,70);
    up_move->setShortcut(QKeySequence(Qt::Key_W));
    left_move->setShortcut(QKeySequence(Qt::Key_A));
    right_move->setShortcut(QKeySequence(Qt::Key_D));
    down_move->setShortcut(QKeySequence(Qt::Key_S));
    connect(left_move,&QPushButton::clicked,this,[=](){
        if(moveDirect!=SnakeDirect::RIGHT)
            moveDirect=SnakeDirect::LEFT;
    });
    connect(right_move,&QPushButton::clicked,this,[=](){
        if(moveDirect!=SnakeDirect::LEFT)
            moveDirect=SnakeDirect::RIGHT;
    });
    connect(up_move,&QPushButton::clicked,this,[=](){
        if(moveDirect!=SnakeDirect::DOWN)
            moveDirect=SnakeDirect::UP;
    });
    connect(down_move,&QPushButton::clicked,this,[=](){
        if(moveDirect!=SnakeDirect::UP)
            moveDirect=SnakeDirect::DOWN;
    });
    QPushButton* exit=new QPushButton(this);
    exit->setGeometry(1400,1100,100,100);
    exit->setIcon(QIcon(":/res/back.png"));
    exit->setStyleSheet("border:0px");
    sbn->setStyleSheet("border:0px");
    ebn->setStyleSheet("border:0px");
    QMessageBox* mb=new QMessageBox(this);
    QPushButton* pb1=new QPushButton("Ok");
    QPushButton* pb2=new QPushButton("Cancel");
    mb->addButton(pb1,QMessageBox::AcceptRole);
    mb->addButton(pb2,QMessageBox::RejectRole);
    mb->setWindowTitle("贪吃蛇");
    mb->setText("确定退出游戏吗");
    connect(exit,&QPushButton::clicked,this,[=](){
        mb->show();
        mb->exec();
        if(mb->clickedButton()==pb1)
        {
           this->close();
        }
        else
        {
             mb->close();
        }
    });
}

void gamehome::paintEvent(QPaintEvent *event)
{
    QPainter* pa=new QPainter(this);
    pa->drawPixmap(0,0,1200,1200,QPixmap(":res/gamebackground.png"));
    QPixmap pm;
    //    qDebug()<<snakeList.size();
    if(snakeList.size())
    {
        if(moveDirect==SnakeDirect::UP)
        {
            pm.load(":res/up.png");
        }
        else if(moveDirect==SnakeDirect::DOWN)
        {
            pm.load(":res/down.png");
        }
        else if(moveDirect==SnakeDirect::LEFT)
        {
            pm.load(":res/left.png");
        }
        else
        {
            pm.load(":res/right.png");
        }
        auto head=snakeList.front();
        pa->drawPixmap(head.x(),head.y(),head.width(),head.height(),pm);

        pm.load(":res/Bd.png");
        for(int i=1;i<snakeList.size()-1;i++)
        {
            auto body=snakeList.at(i);
            pa->drawPixmap(body.x(),body.y(),body.width(),body.height(),pm);
        }
        auto tail=snakeList.back();

        pa->drawPixmap(tail.x(),tail.y(),tail.width(),tail.height(),pm);
    }
    //绘制食物
    pm.load(":res/food.png");
    pa->drawPixmap(FoodRect.x(),FoodRect.y(),FoodRect.width(),FoodRect.height(),pm);

    //绘制分数
    pm.load(":res/sorce.png");
    pa->drawPixmap(1300,0,100,80,pm);
    QPen pen;
    pen.setColor(Qt::red);
    pa->setPen(pen);
    QFont font("方正舒体",16);
    pa->setFont(font);
    pa->drawText(1332,35,QString("%1").arg(snakeList.size()*10-30));

    if(checkFail())     //处理gameover的情况
    {
        timer->stop();
        QPen pen;
        pen.setColor(Qt::red);
        pa->setPen(pen);
        QFont font("方正舒体",50);
        pa->setFont(font);
        pa->drawText(500,600,QString("Game Over"));

        //更新历史最高分数
        int cur_score=snakeList.size()*10-30;
        QFile file(":res/maxscore.text");
        file.open(QIODevice::ReadWrite);
        int his_score=file.readAll().toInt();
        if(cur_score>his_score)
        {
            QString score=QString::number(cur_score);
            file.write(score.toUtf8(),score.size());
        }
        file.close();

    }

}

void gamehome::moveUp()
{
    QPointF leftTop;
    QPointF rightBottom;
    auto snakeNode=snakeList.front();
    int headX=snakeNode.x();
    int headY=snakeNode.y();
    if(headY<0)
    {
        leftTop=QPointF(headX,this->height()-kSnakeNodeHeight);
    }
    else
    {
        leftTop=QPointF(headX,headY-kSnakeNodeHeight);
    }
    rightBottom=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);
    snakeList.push_front(QRectF(leftTop,rightBottom));
}

void gamehome::moveDown()
{
    QPointF leftTop;
    QPointF rightBottom;
    auto snakeNode=snakeList.front();
    int headX=snakeNode.x();
    int headY=snakeNode.y();
    if(headY>1200)
    {
        leftTop=QPointF(headX,0);
    }
    else
    {
        leftTop=QPointF(headX,headY+kSnakeNodeHeight);
    }
    rightBottom=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);
    snakeList.push_front(QRectF(leftTop,rightBottom));
}

void gamehome::moveLeft()
{
    QPointF leftTop;
    QPointF rightBottom;
    auto snakeNode=snakeList.front();
    int headX=snakeNode.x();
    int headY=snakeNode.y();
    if(headX<0)
    {
        leftTop=QPointF(1200-kSnakeNodeWidth,headY);
    }
    else
    {
        leftTop=QPointF(headX-kSnakeNodeWidth,headY);
    }
    rightBottom=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);
    snakeList.push_front(QRectF(leftTop,rightBottom));
}

void gamehome::moveRight()
{
    QPointF leftTop;
    QPointF rightBottom;
    auto snakeNode=snakeList.front();
    int headX=snakeNode.x();
    int headY=snakeNode.y();
    if(headX>=1150)
    {
        leftTop=QPointF(0,headY);
    }
    else
    {
        leftTop=QPointF(headX+kSnakeNodeWidth,headY);
    }
    rightBottom=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);
    snakeList.push_front(QRectF(leftTop,rightBottom));
}

void gamehome::setSpeed(int speed)
{
    kDefaultTimeout=speed;
}



bool gamehome::checkFail()
{
    for(int i=0;i<snakeList.size();i++)
    {
        for(int j=i+1;j<snakeList.size();j++)
        {
            if(snakeList.at(i)==snakeList.at(j))
                return true;
        }
    }
    return false;
}

void gamehome::createNewFood()
{
    FoodRect=QRectF(qrand()%(1200/kSnakeNodeWidth)*kSnakeNodeWidth,qrand()%(1200/kSnakeNodeHeight)*kSnakeNodeHeight,kSnakeNodeWidth,kSnakeNodeHeight);

}
